/**
 *  This file is part of "c-genericlinkedlist".
 *
 *  "c-genericlinkedlist" is free software:
 *  you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation, either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  "c-genericlinkedlist" is distributed
 *  in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with "c-genericlinkedlist".
 *  If not, see <http://www.gnu.org/licenses/>
 *
 */

#include "list.h"

No* criarNo()
{
	No *N = (No*) malloc(sizeof(No));
	N->valor = N->prox = N->anterior = NULL;
	return(N);
}

void liberarNo(No* N)
{
	free(N);
}

Lista* criarLista()
{
	Lista *L = (Lista*) malloc(sizeof(Lista));
	L->inicio = criarNo();
	L->fim = criarNo();
	
	L->inicio->prox = L->fim;
	L->fim->anterior = L->inicio;
	
	L->size = 0;
	return(L);
}

void liberarLista(Lista *L)
{
	if( taVazia(L) ) {
		liberarNo(L->inicio);
		liberarNo(L->fim);
		free(L);
	}
	else {
		No *aux;
		for(aux = L->inicio->prox; aux != L->fim; aux = aux->prox) {
			
		}
	}
	
}

int taVazia(Lista *L)
{
	// ou if (L->size == 0) , da no mesmo
	if(L->inicio->prox == L->fim)
		return 1;
	else
		return 0;
}

void printInt(Lista *L)
{
	if( taVazia(L) )
		printf("A lista esta vazia.\n");
	else
	{
		No *aux;
		for(aux = L->inicio->prox; aux != L->fim; aux = aux->prox)
			printf("(%d)\n", *(int*)aux->valor );
	}
}

void inserirInicio(Lista *L, tipo_lista dado)
{
	if( taVazia(L) )
	{
		No *novo = criarNo();
		novo->valor = dado;
		
		L->inicio->prox = novo;
		L->fim->anterior = novo;
		
		novo->prox = L->fim;
		novo->anterior = L->inicio;
		
		L->size++;
	}
	else
	{
		No *novo = criarNo();
		novo->valor = dado;
		
		No *aux = L->inicio->prox;
		
		aux->anterior = novo;
		novo->prox = aux;
		
		L->inicio->prox = novo;
		novo->anterior = L->inicio;
		
		L->size++;
	}
}

void inserirFim(Lista *L, tipo_lista dado)
{
	if( taVazia(L) )
		inserirInicio(L, dado);
	else
	{
		No *novo = criarNo();
		novo->valor = dado;
		
		No *aux = L->fim->anterior;
		
		aux->prox = novo;
		novo->anterior = aux;
		
		novo->prox = L->fim;
		L->fim->anterior = novo;
		
		L->size++;
	}
}

void inserirOrdenado(Lista *L, int(*compara)(const void*, const void*), tipo_lista dado)
{
	if( taVazia(L) )
		inserirInicio(L, dado);
	else
	{
		No *aux;
		for(aux = L->inicio->prox; aux != L->fim; aux = aux->prox)
		{
			if(compara(aux->valor, dado) >= 0)
				break;
		}
		if( aux == L->fim )
			inserirFim(L, dado);
		else
		{
			No *novo = criarNo();
			novo->valor = dado;
			
			aux->anterior->prox = novo;
			novo->anterior = aux->anterior;
			
			novo->prox = aux;
			aux->anterior = novo;
			
			L->size++;
		}
	}
}

tipo_lista buscar(Lista* L, tipo_lista elem)
{
	if( taVazia(L) )
		return NULL;
	else {
		
	}
}

tipo_lista buscarOrdenado(Lista* L, tipo_lista elem)
{
}


void removerInicio(Lista *L)
{
	if( taVazia(L) )
		printf("A lista ja esta vazia.\n");
	else {
		No *saida = L->inicio->prox;
		
		saida->prox->anterior = L->inicio;
		L->inicio->prox = saida->prox;
		
		liberarNo(saida);
		L->size--;
	}
}

void removerFim(Lista *L)
{
	if( taVazia(L) )
		printf("A lista ja esta vazia.\n");
	else {
		No *saida = L->fim->anterior;
		
		saida->anterior->prox = L->fim;
		L->fim->anterior = saida->anterior;
		
		liberarNo(saida);
		L->size--;
	}
}

void removerElem(Lista *L, tipo_lista dado)
{
	if( taVazia(L) )
		printf("A lista ja esta vazia.\n");
	else {
		/* implementar a busca */
		L->size--;
	}
}

